package com.zzyl.nursing.service.impl;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.*;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.DeviceFunctionDTO;
import com.zzyl.nursing.dto.ElderlyDto;
import com.zzyl.nursing.dto.UserLoginRequestDto;
import com.zzyl.nursing.service.WechatService;
import com.zzyl.nursing.util.DateTimeZoneConverter;
import com.zzyl.nursing.vo.LoginVo;
import org.apache.poi.hssf.record.DVALRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.FamilyMemberMapper;
import com.zzyl.nursing.service.IFamilyMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 老人家属Service业务层处理
 *
 * @author ruoyi
 * @date 2025-04-26
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService {
    @Autowired
    private FamilyMemberMapper familyMemberMapper;

    static List<String> DEFAULT_NICKNAME_PREFIX = ListUtil.of(
            "生活更美好",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝"
    );

    /**
     * 查询老人家属
     *
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id) {
        return getById(id);
    }

    /**
     * 查询老人家属列表
     *
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember) {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 新增老人家属
     *
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int insertFamilyMember(FamilyMember familyMember) {
        return save(familyMember) ? 1 : 0;
    }

    /**
     * 修改老人家属
     *
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember) {
        return updateById(familyMember) ? 1 : 0;
    }

    /**
     * 批量删除老人家属
     *
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除老人家属信息
     *
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    @Autowired
    private WechatService wechatService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IoTDAClient client;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 小程序端登录
     *
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto dto) {

        //获取openid  微信接口获取
        String openid = wechatService.getOpenid(dto.getCode());

        //根据openid查询用户信息
        FamilyMember familyMember = getOne(Wrappers.<FamilyMember>lambdaQuery().eq(FamilyMember::getOpenId, openid));

        //如果用户为空，构建用户，赋值一个openid
        if (ObjectUtil.isEmpty(familyMember)) {
            familyMember = FamilyMember
                    .builder()
                    .openId(openid)
                    .build();
        }

        //获取用户的手机号  微信接口获取
        String phone = wechatService.getPhone(dto.getPhoneCode());

        //保存或更新用户
        insertOrUpdateFamilyMember(familyMember, phone);

        //生成token返回
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", familyMember.getId());
        claims.put("userName", familyMember.getName());

        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setNickName(familyMember.getName());
        loginVo.setToken(token);

        return loginVo;
    }


    /**
     * 添加家人
     *
     * @param dto
     */
    @Override
    public void addElders(ElderlyDto dto) {
        String idCard = dto.getIdCard();
        //查询该身份证号的老人
        Elder elder = familyMemberMapper.selectIdCard(idCard);
        if (ObjectUtil.isEmpty(elder)) {
            throw new RuntimeException("该身份证号的老人未入住");
        }
        //家人id
        Long userId = UserThreadLocal.getUserId();
        Long elderId = elder.getId();
        FamilyOlder familyOlder = new FamilyOlder();
        familyOlder.setElderId(elderId);
        familyOlder.setFamilyMemberId(userId);
        familyOlder.setRemark(dto.getRemark());
        FamilyMember familyMember = familyMemberMapper.selectFamilyMemberById(userId);
        if (familyMember == null) {
            throw new RuntimeException("未找到当前用户信息，userId：" + userId);
        }
        familyOlder.setCreateTime(LocalDateTime.now());
        familyOlder.setUpdateTime(LocalDateTime.now());
        familyOlder.setCreateBy(familyMember.getId());
        familyOlder.setUpdateBy(familyMember.getId());
        familyMemberMapper.addElders(familyOlder);
    }

    /**
     * 分页查询家人列表
     *
     * @param param
     * @return
     */
    @Override
    public List<ElderlyDetail> pageList(FamilyOlderParam param) {
        PageHelper.startPage(param.getPage(), param.getPageSize());

        Long userId = UserThreadLocal.getUserId();

        //2.执行查询
        List<ElderlyDetail> list = familyMemberMapper.pageList(param, userId);

        return list;
    }

    /**
     * 查询家人列表
     *
     * @return
     */
    @Override
    public List<FamilyOlder> selectList() {
        List<FamilyOlder> list = familyMemberMapper.list();
        return list;
    }

    /**
     * 查询健康数据
     *
     * @param iotId
     * @return
     */
    @Override
    public List<DeviceEvent> queryServiceProperties(String iotId) {
        Object o = redisTemplate.opsForHash().get(CacheConstants.IOT_DEVICE_LAST_DATA, iotId);
        List<DeviceEvent> deviceDataList = new ArrayList<>();
        List<DeviceData> list = JSONUtil.toList(o.toString(), DeviceData.class);
        list.forEach(deviceData -> {
            DeviceEvent deviceEvent = new DeviceEvent();
            deviceEvent.setFunctionId(deviceData.getFunctionId());
            deviceEvent.setValue(deviceData.getDataValue());
            deviceEvent.setEventTime(deviceData.getAlarmTime());
            deviceDataList.add(deviceEvent);
        });
        return deviceDataList;
    }

    @Override
    public List<Map<String, Object>> queryDeviceDataListByDay(DeviceFunctionDTO dto) {
        // 把开始时间的戳转换成LocaldateTime类型的日期
        LocalDateTime startTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dto.getStartTime()), ZoneId.systemDefault());
        startTime = DateTimeZoneConverter.utcToShanghai(startTime);
        // 获取当天最小时间
        startTime = startTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
        // 把结束时间的戳转换成LocaldateTime类型的日期
        LocalDateTime endTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dto.getEndTime()), ZoneId.systemDefault());
        endTime = DateTimeZoneConverter.utcToShanghai(endTime);
        endTime = endTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
        String iotId = dto.getIotId();
        String functionId = dto.getFunctionId();
        // 1. 查询数据库中已有的每小时平均值
        List<Map<String, Object>> dbResult = familyMemberMapper.selectDaysValue(
                iotId, functionId, startTime, endTime);

        // 2. 构建完整的时间键 -> 默认值为 0.0(key:dateTime,value:dataValue)
        Map<String, Double> avgMap = new HashMap<>();
        LocalDateTime begin = startTime;
        while (begin.isBefore(endTime)) {
            String hourKey = begin.toLocalTime().toString();
            avgMap.put(hourKey, 0.0); // 平均数初始设为 0.0
            begin = begin.plusHours(1);
        }

        // 3. 填充数据库中查到的数据
        if (!CollectionUtil.isEmpty(dbResult)) {
            for (Map<String, Object> row : dbResult) {
                String str = (String) row.get("dateTime");
                LocalTime hourTime = LocalTime.parse(str);
                String hourKey = hourTime.toString();
                Double avg = (Double) row.get("dataValue");
                avgMap.put(hourKey, avg);
            }
        }

        // 4. 构造最终结果
        List<Map<String, Object>> list = new ArrayList<>();
        begin = startTime;
        while (begin.isBefore(endTime)) {
            String hourKey = begin.toLocalTime().toString();
            Double dataAvg = avgMap.get(hourKey); // 可能为 null

            Map<String, Object> map = new HashMap<>();
            map.put("dateTime", hourKey);
            if (dataAvg == null) {
                dataAvg = 0.0;
            } else {
                // 四舍五入保留一位小数
                dataAvg = Math.ceil(dataAvg);
            }
            map.put("dataValue", dataAvg);
            list.add(map);
            begin = begin.plusHours(1);
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> queryDeviceDataListByWeek(DeviceFunctionDTO dto) {
        LocalDateTime startTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dto.getStartTime()), ZoneId.systemDefault());
        startTime = DateTimeZoneConverter.utcToShanghai(startTime);
        LocalDate startTimeLocalDate = startTime.toLocalDate();

        // 把结束时间的戳转换成Localdate类型的日期
        LocalDateTime endTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dto.getEndTime()), ZoneId.systemDefault());
        endTime = DateTimeZoneConverter.utcToShanghai(endTime);
        LocalDate endTimeLocalDate = endTime.toLocalDate();

        String iotId = dto.getIotId();
        String functionId = dto.getFunctionId();
        // 1. 查询数据库中已有的每小时平均值
        List<Map<String, Object>> result = familyMemberMapper.selectWeeksValue(
                functionId, iotId, startTime, endTime);
        // 2. 构建完整的时间键 -> 默认值为 0.0(key:dateTime,value:dataValue)
        Map<String, Double> map = new HashMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.dd");
        LocalDate begin = startTimeLocalDate;
        while (begin.isBefore(endTimeLocalDate)) {
            String hourKey = begin.format(formatter);
            map.put(hourKey, 0.0); // 平均数初始设为 0.0
            begin = begin.plusDays(1);
        }
        //3.把数据库查到的数据填充到map中
        if (!CollectionUtil.isEmpty(result)) {
            for (Map<String, Object> row : result) {
                String dayKey = (String) row.get("dateTime");
                Double avg = (Double) row.get("dataValue");
                map.put(dayKey, avg);
            }
        }
        // 4. 构造最终结果
        List<Map<String, Object>> list = new ArrayList<>();
        map.forEach((dayKey, avg) -> {
            Map<String, Object> map1 = new HashMap<>();
            map1.put("dateTime", dayKey);
            map1.put("dataValue", Math.ceil(avg));
            list.add(map1);
        });

        return list;
    }


    /**
     * 保存或更新用户
     *
     * @param familyMember
     * @param phone
     */
    private void insertOrUpdateFamilyMember(FamilyMember familyMember, String phone) {

        //判断手机号与数据库的手机号是否一致
        if (ObjectUtil.notEqual(familyMember.getPhone(), phone)) {
            familyMember.setPhone(phone);
        }
        //判断是否存在id，如果存在id，则更新，不存在则保存
        if (ObjectUtil.isNotEmpty(familyMember.getId())) {
            updateById(familyMember);
            return;
        }
        //获取用户的昵称
        int index = (int) (Math.random() * DEFAULT_NICKNAME_PREFIX.size());
        String nickName = DEFAULT_NICKNAME_PREFIX.get(index) + StringUtils.substring(phone, 7, 11);
        familyMember.setName(nickName);
        //保存
        save(familyMember);

    }
}
